#ifndef __MY_SERVER__
#define __MY_SERVER__
#include <time.h>
#include "Data.hpp"
#include "httplib.h" //默认线程池大小为8个
#include <iconv.h>
extern Cloud::DataManger *data;
namespace Cloud
{
    class Server // 服务器业务处理类
    {
    private:
        int server_port;
        string server_ip;
        string download_prefix;
        httplib::Server _server;

    public:
        Server()
        {
            server_ip = Cloud::Config::GetInstance()->GetServerIp();
            server_port = Cloud::Config::GetInstance()->GetServerPort();
            download_prefix = Cloud::Config::GetInstance()->GetDownLoadprefix();
        }
        static string TimeToString(time_t &t)
        {
            std::string tmp = std::ctime(&t);
            return tmp;
        }
        static string GetETags(const Cloud::BackupInfo &Info) // 设置ETags用来表示一个文件是否修改，若没修改，则当下次下载链接到来
                                                              // 客户端直接在缓存中取
        {
            stringstream etag;
            etag << FileUtil(Info.realpath).GetFileName() << "-" << to_string(Info.fsize) << "-" << to_string(Info.mtime);
            // string etag = FileUtil(Info.realpath).GetFileName();
            // etag += "-";
            // etag += to_string(Info.fsize);
            // etag += "-";
            // etag += to_string(Info.mtime);
            return etag.str();
        }

        void RunModule()
        {

            _server.Post("/upload", [](const httplib::Request &req, httplib::Response &res)
                         {
                             auto ret = req.has_file("file");
                             if (ret == false)
                             {
                                res.status=400;
                                 return;
                             }
                 
                             struct httplib::MultipartFormData item;
                             item = req.get_file_value("file");
                         
                             string back_dir = Cloud::Config::GetInstance()->GetBackDir();
                             string realpath = back_dir+Cloud::FileUtil(item.filename).GetFileName();

                             Cloud::FileUtil fu(realpath);
                             fu.SetCentent(item.content);
                             Cloud::BackupInfo info(realpath);
                             data->Insert(info); 
                            res.status = 200; });
            string download_url = download_prefix + "(.*)";
            _server.Get(download_url, [](const httplib::Request &req, httplib::Response &res)
                        {
                            // 获取下载文件的备份信息
                            Cloud::BackupInfo Info;
                            data->GetOneByUrl(req.path, &Info);
                            // 判断下载文件是否压缩，压缩先解压，然后删除压缩包
                            if (Info.pack_flag == true)
                            {
                                FileUtil fu(Info.packpath);
                                fu.UnCompress(Info.realpath);
                                Info.pack_flag = false;
                                Info.packRunning=false;
                                data->Update(Info);
                                fu.Remove();
                            }
                            bool retrans = false; // 断点续传标志位
                            FileUtil fu(Info.realpath);
                            string old_etags;
                            // 判读正常下载还是断点续传
                            if (req.has_header("If-Range"))//文件唯一标识符
                            {
                                old_etags = req.get_header_value("If-Range");
                                if (old_etags == GetETags(Info)) // 如果请求中的If-Range和服务器的etag不一致，则正常下载
                                {
                                    retrans = true;
                                }
                            }               
                            if (retrans) // 断点续传
                            {

                                //根据Range字段，get_header_value("Range")获取到字段值，通过解析，取出begin和end，对body进行截断 
                                fu.GetCentent(&res.body);
                                res.set_header("ETag", GetETags(Info));
                                res.set_header("Accept-Ranges", "bytes");
                                res.set_header("Content-Type", "application/octet-stream");
                                //res.set_hreader("Content-Range","bytes start-end/fsize") httplib自己进行填充了
                                res.status = 206;
                            }
                            else
                            {
    
                                // 获取下载文件正文内容
                                fu.GetCentent(&res.body);
                                // 设置响应头部字段
                                //  设置ETags: "filename-size-mtime⼀个能够唯⼀标识⽂件的数据"
                                res.set_header("ETag", GetETags(Info));                    // 用来表示客户端请求文件与服务器备份文件是否一致
                                res.set_header("Content-Type", "application/octet-stream"); // 定义网络文件的类型，以二进制流方式处理
                                res.set_header("Accept-Ranges", "bytes");                   // 告诉客户端服务器支持断点续传
                                res.status = 200;
                            } });

            _server.Get("/", [](const httplib::Request &req, httplib::Response &res)
                        {
                            // 1.获取备份文件所有信息
                            vector<Cloud::BackupInfo> array;
                            data->GetAll(&array);
                            // 2. 根据所有备份信息，组织html文件数据
                            stringstream ss;
                            ss << "<html><head><meta charset=\"UTF-8\"><title>Download</title></head>";
                            ss << "<body><h1>Download</h1><table>";
                            for (auto &e : array)
                            {
                                ss << "<tr>";
                                string filename = FileUtil(e.realpath).GetFileName();
                                ss << "<td><a href='" << e.url << "'>" << filename << "</a></td>";
                                ss << "<td align='right'>" << TimeToString(e.atime) << "</td>";
                                ss << "<td align='right'>" << e.fsize / 1024 << "k </td>";
                                ss << "</tr>";  
                            }
                            ss << "</table></body></html>";
                            res.body = ss.str();
                            res.set_header("Content-Type", "text/html");
                            res.status=200; });
            _server.Get("/listshow", [](const httplib::Request &req, httplib::Response &res) { // 1.获取备份文件所有信息
                vector<Cloud::BackupInfo> array;
                data->GetAll(&array);
                // 2. 根据所有备份信息，组织html文件数据
                stringstream ss;
                ss << "<html><head><meta charset=\"UTF-8\"><title>Download</title></head>";
                ss << "<body><h1>Download</h1><table>";
                for (auto &e : array)
                {
                    ss << "<tr>";
                    string filename = FileUtil(e.realpath).GetFileName();
                    ss << "<td><a href='" << e.url << "'>" << filename << "</a></td>";
                    ss << "<td align='right'>" << TimeToString(e.atime) << "</td>";
                    ss << "<td align='right'>" << e.fsize / 1024 << "k </td>";
                    ss << "</tr>";
                }
                ss << "</table></body></html>";
                res.body = ss.str();
                res.set_header("Content-Type", "text/html");
                res.status = 200;

            });
            _server.listen(server_ip.c_str(), server_port);
        }
    };
}

#endif